# koroFileHeader at Yungoal acer
# Create: 2023-10-25 17:15:44
# LastEdit: 2023-10-26 17:11:48
"""列出当前账号可以访问的资源信息
https://next.api.aliyun.com/api/ResourceManager/2020-03-31/ListResources
"""
__author__ = '749B'
# pylint: disable=import-error, wrong-import-position

if __name__ == '__main__':
    # 导入路径
    from pathlib import Path
    BASE_DIR = Path(__file__).resolve().parent.parent
    import sys
    sys.path.append(str(BASE_DIR))
    # Django 初始化
    import django
    from django.conf import settings
    from ygcmp import settings as my_settings
    settings.configure(**{ k: v for k, v in vars(my_settings).items() if k.isupper() })
    django.setup()


import logging
import time

# pylint: disable=ungrouped-imports
from django.utils import timezone

from apps.resourcemanager import models
from utils.alibabacloud.resourcemanager import list_resources

from tasks.thread_task import BaseTask


class SyncResources(BaseTask):

    def __init__(self, account: models.Account):
        self.account = account
        self.user = account.user_set.filter(status=True).first()
        self._client = None
        super().__init__(task_name=self.account.name)

        self.logger = logging.getLogger(f"tasks.{self.__class__.__name__}")
        self.logger.success = lambda msg, *args, **kwargs: self.logger.log(25, msg, *args, **kwargs)

    @BaseTask.set_task_info
    def run(self):
        self.logger.info('同步资源信息任务开始: %s', self.task_key[1])
        sync_time = timezone.now()
        start_time = time.time()
        rgid_map = dict(
            models.ResourceGroup.objects
            .filter(acc=self.account)
            .values_list('rid', 'id'))
        new_objs = []
        changed_objs_map = {}
        # 创建新资源前，获取到已经存在的资源信息，只要当前账号并且是没有del_time的（当前账号下的未删除资源）
        # QuerySet 是惰性的，调用list()强制执行，确保拿出当前的结果，而不是创建了新资源后的结果
        res_in_db = models.Resource.objects.filter(
            resource_group__acc=self.account, dtime__isnull=True)
        list(res_in_db)
        for resource in list_resources(self.user.rm_client):
            try:
                obj = res_in_db.get(
                    rid=resource['ResourceId'],
                    rgid=resource['ResourceGroupId'],
                    service=resource['Service'],
                    resource_type=resource['ResourceType'],
                    region_id=resource['RegionId'],
                    )
                obj, fields = obj.changed_from_map(
                    sync_time=sync_time,
                    resource_group_id=rgid_map[resource['ResourceGroupId']])
                for field in fields:
                    changed_objs_map.setdefault(field, []).append(obj)
            except models.Resource.DoesNotExist:
                res_obj = models.Resource.create_from_map(
                    resource, resource_group_id=rgid_map[resource['ResourceGroupId']])
                new_objs.append(res_obj)
        duration_time_request = time.time() - start_time
        if new_objs:
            models.Resource.objects.bulk_create(new_objs)
            duration_time_bulk_create = time.time() - start_time
            self.logger.info(
                '批量创建资源记录: %s 数量=%d 耗时=%.2f秒', 
                self.user.account, len(new_objs), duration_time_bulk_create)
        else:
            self.logger.info(
                '同步资源信息: %s 无新增资源 请求耗时=%.2f秒', 
                self.user.account, duration_time_request)
        for field, changed_objs in changed_objs_map.items():
            models.Resource.objects.bulk_update(changed_objs, [field])
            self.logger.info(
                '批量更新资源记录: %s field=%s 数量=%d',
                self.user.account, field, len(changed_objs))
        # 没有更新到的记录，添加dtime字段值。一次修改多个对象
        (
            models.Resource.objects
            .filter(resource_group__acc=self.account)
            .filter(utime__lt=sync_time)
            .update(dtime=timezone.now())
            )
        self.logger.info('同步资源信息任务完成: %s', self.task_key[1])


if __name__ == '__main__':
    for acc in models.Account.objects.all():
        task = SyncResources(acc)
        started = task.start()
        if started:
            print('同步资源信息开始', task.task_key[1])
        else:
            print('任务未开始', task.task_start_msg)
